 #include <spiff.h>

void initNvs(){
     esp_err_t ret = nvs_flash_init();
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND)
    {
        ESP_ERROR_CHECK(nvs_flash_erase());
        ret = nvs_flash_init();
    }
    if (ret==ESP_OK)
    {
        ESP_LOGI("NVS Init","nvs init success");
    }else{
        ESP_LOGE("NVS Init","%s",esp_err_to_name(ret));
        
    }
    
}


esp_err_t init_spiffs(void)
{
    ESP_LOGI("init spiffs", "Initlizating SPIFFS");
    esp_vfs_spiffs_conf_t spiff_conf = {
        .base_path = "/spiffs",
        .partition_label = NULL,
        .max_files = 5,
        .format_if_mount_failed = true,
    };

    esp_err_t ret = esp_vfs_spiffs_register(&spiff_conf);

    if (ret != ESP_OK)
    {
        if (ret == ESP_FAIL)
        {
            ESP_LOGE(SPIFF_TAG, "Failed to mount or format filesystem");
        }
        else if (ret == ESP_ERR_NOT_FOUND)
        {
            ESP_LOGE(SPIFF_TAG, "Failed to find SPIFFS partition");
        }
        else
        {
            ESP_LOGE(SPIFF_TAG, "Failed to initialize SPIFFS (%s)", esp_err_to_name(ret));
        }
        return ret;
    }
    size_t total = 0, used = 0;
    ret = esp_spiffs_info(NULL, &total, &used);
    list_spiffs_files();
    if (ret != ESP_OK)
    {
        ESP_LOGE(SPIFF_TAG, "Failed to get SPIFFS partition information");
    }
    else
    {
        ESP_LOGE(SPIFF_TAG, "SPIFFS partition size: total: %d bytes, used: %d bytes  rate:%f", total, used, (float)((float)used / total));
    }
    return ESP_OK;
}


// 定义 MIN 宏，返回两个值中的较小值
#ifndef MIN
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#endif
// 读取文件并以十六进制格式打印
esp_err_t dump_file_hex(const char *filename)
{
    if (filename == NULL)
    {
        return ESP_ERR_INVALID_ARG;
    }

    // 构建完整路径
    char file_path[264];
    snprintf(file_path, sizeof(file_path), "/spiffs/%s", filename);

    // 打开文件
    FILE *file = fopen(FILE_PATH, "rb"); // 以二进制模式读取
    if (file == NULL)
    {
        ESP_LOGE(SPIFF_TAG, "Failed to open file: %s", filename);
        return ESP_FAIL;
    }

    // 获取文件大小
    fseek(file, 0, SEEK_END);
    size_t file_size = ftell(file);
    fseek(file, 0, SEEK_SET);

    ESP_LOGI(SPIFF_TAG, "Dumping file: %s (size: %zu bytes)", filename, file_size);

    // 分配缓冲区
    uint8_t *buffer = malloc(file_size);
    if (buffer == NULL)
    {
        ESP_LOGE(SPIFF_TAG, "Memory allocation failed for file: %s", filename);
        fclose(file);
        return ESP_ERR_NO_MEM;
    }

    // 读取文件内容
    size_t bytes_read = fread(buffer, 1, file_size, file);
    if (bytes_read != file_size)
    {
        ESP_LOGE(SPIFF_TAG, "Failed to read entire file: %s", filename);
        free(buffer);
        fclose(file);
        return ESP_FAIL;
    }

    // 关闭文件
    fclose(file);

    // 以16字节为一组进行十六进制转储
    const size_t chunk_size = 16;
    for (size_t i = 0; i < file_size; i += chunk_size)
    {
        size_t bytes_in_chunk = MIN(chunk_size, file_size - i);
        ESP_LOG_BUFFER_HEXDUMP(SPIFF_TAG, &buffer[i], bytes_in_chunk, ESP_LOG_INFO);
    }

    // 释放缓冲区
    free(buffer);

    return ESP_OK;
}

void list_spiffs_files(void)
{
    char *title = "list_spiffs_files";
    ESP_LOGI(title, "Listing files in SPIFFS:");

    DIR *dir = opendir("/spiffs");
    if (dir == NULL)
    {
        ESP_LOGE(title, "Failed to open directory");
        return;
    }

    struct dirent *entry;
    while ((entry = readdir(dir)) != NULL)
    {
        // 打印文件名和文件类型
        if (entry->d_type == DT_DIR)
        {
            ESP_LOGE(title, "Directory: %s", entry->d_name);
        }
        else if (entry->d_type == DT_REG)
        {
            // 获取文件大小
            char file_path[264];
            snprintf(file_path, sizeof(file_path), "/spiffs/%s", entry->d_name);

            FILE *f = fopen(file_path, "r");
            if (f)
            {
                fseek(f, 0, SEEK_END);
                size_t size = ftell(f);
                fclose(f);
                ESP_LOGE(title, "File: %s (size: %zu bytes)", entry->d_name, size);
            }
            else
            {
                ESP_LOGE(title, "File: %s (size: unknown)", entry->d_name);
            }
        }
        else
        {
            ESP_LOGI(title, "Other: %s (type: %d)", entry->d_name, entry->d_type);
        }
    }

    closedir(dir);
}
